package progetto6.jade;

import java.io.IOException;
import java.util.ArrayList;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;

public class Player extends Agent {
	
	@SuppressWarnings("serial")
	private class Ender extends CyclicBehaviour{

		@Override
		public void action() {
			MessageTemplate tpl = MessageTemplate.MatchPerformative(ACLMessage.CANCEL);
			ACLMessage message = myAgent.receive(tpl);
			if (message != null) {
//				System.out.println("Player #"+id+" pronto ad essere eliminato");
				myAgent.doDelete();
			}else{
//				System.out.println("Player #"+id+":Ender block");
				block();
			}
			
		}
	}
	
	@SuppressWarnings("serial")
	private class Game extends Behaviour{
		
		private int step = 0;
		private boolean end = false;
		
		@Override
		public void action() {
			switch (step) {
			case 0:	
				ACLMessage message = new ACLMessage(ACLMessage.INFORM);
				message.addReceiver(manager);
				ArrayList<Object> content = new ArrayList<Object>();
				content.add(id);
				content.add(strategy.getNext());
				try {
					message.setContentObject(content);
				} catch (IOException e) {
					e.printStackTrace();
				}
				myAgent.send(message);
				step++;
//				System.out.println("Player #"+id+": ha inviato la giocata");
				break;
			case 1:
				MessageTemplate tpl = MessageTemplate.MatchPerformative(ACLMessage.INFORM);
				message = myAgent.receive(tpl);
				if (message != null) {
					if (message.getConversationId() != null && message.getConversationId().equals("EG")) {
						end = true;
						myAgent.addBehaviour(new Registration());
					}
					try {
						strategy.esit(((Integer) message.getContentObject())
								.intValue());
					} catch (UnreadableException e) {
						System.out.println("COD6");
						e.printStackTrace();
					}
					step = 0;
//					System.out.println("Player #"+id+": ha ricevuto l'esito");
				} else {
					block();
				}
				break;
			default:
				assert false;//Jade disattiva le asserzioni WOW!
				break;
			}
		}

		@Override
		public boolean done() {
			return end;
		}
		
	}
	
	@SuppressWarnings("serial")
	private class Registration extends Behaviour{
		private int step = 0;

		@Override
		public void action() {
			switch (step) {
			case 0:
				if(strategy!=null){
					AbstractStrategy s = (AbstractStrategy) strategy;
					System.out.println("Player #"+id+":"+strategy.toString()+":Score: D="+s.getScore(Choice.D)+", C="+s.getScore(Choice.C));

				}
				ACLMessage message = new ACLMessage(ACLMessage.SUBSCRIBE);
				message.addReceiver(manager);
				if(strategy != null){
					ArrayList<Object> content = new ArrayList<Object>();
					content.add(id);
					content.add(strategy);
					try {
						message.setContentObject(content);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				myAgent.send(message);
				step++;
				System.out.println("Player #"+id+": ha inviato la richiesta di registrazione");
				break;
			case 1:
				MessageTemplate tpl = MessageTemplate.MatchPerformative(ACLMessage.SUBSCRIBE);
				message = myAgent.receive(tpl);
				if (message != null) {
					try {
						strategy = (Strategy) message.getContentObject();
					} catch (UnreadableException e) {
						System.out.println("COD5");
						e.printStackTrace();
					}
					myAgent.addBehaviour(new Game());
					System.out.println("Player #"+id+": ha ricevuto la strategia: " + strategy);
				} else {
					block();
				}
				break;
			default:
				assert false;
				break;
			}
			
		}

		@Override
		public boolean done() {
			return step == 2;
		}
	}

	private static final long serialVersionUID = -600148242702641592L;
	private AID manager;
	private Strategy strategy;
	private Integer id;

	@Override
	protected void setup() {
		Object[] arguments = getArguments();
		id = (Integer) arguments[0];
		manager = (AID) arguments[1];
		addBehaviour(new Registration());
		addBehaviour(new Ender());
		System.out.println("Player "+id+" pronto a giocare");
	}
}
